package tree;

/*
 * This code is based on an example provided by Richard Stanford, 
 * a tutorial reader.
 */
import editor.Editor;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.Collections;
import java.util.Vector;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultTreeCellRenderer;

public class DynamicTree extends JPanel {

    protected DefaultMutableTreeNode rootNode;
    protected DefaultTreeModel treeModel;
    protected JTree tree;
    private Toolkit toolkit = Toolkit.getDefaultToolkit();
    protected String path = "C:\\Users\\RoderickNestor\\Documents\\wxPython";
    Editor editor;
    
    public DynamicTree(){
        super(new GridLayout(1, 0));
    }
    
    public void setPath(String path, Editor _editor) {
        
        this.path = path;
        rootNode = new DefaultMutableTreeNode("Root Node");
        //treeModel = new DefaultTreeModel(rootNode);
        treeModel = new DefaultTreeModel(addNodes(null, new File(this.path)));
        treeModel.addTreeModelListener(new MyTreeModelListener());

        tree = new JTree(treeModel);
        //tree = new JTree(addNodes(null, new File(".")));

        tree.setEditable(true);
        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        tree.setShowsRootHandles(true);

        tree.setCellRenderer(new MyRenderer());

        JScrollPane scrollPane = new JScrollPane(tree);
        add(scrollPane);

        this.editor = _editor;

        MouseListener ml = new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                int row = tree.getRowForLocation(e.getX(), e.getY());
                TreePath path = tree.getPathForLocation(e.getX(), e.getY());
                if (row != -1) {
                    if (e.getClickCount() == 2) {
                        //tree.startEditingAtPath(path);
                        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
                        if (node == null) {
                            return;
                        }
                        File node_file = new File(node.getParent() + File.separator + node);
                        if (node_file.exists()) {
                            editor.panelSouth.setStatus(node.toString());
                            editor.tab.addTab(node.getParent() + File.separator + node);
                        }
                    }
                }
            }
        };
        tree.addMouseListener(ml);

        /*tree.addTreeSelectionListener(new TreeSelectionListener() {
         public void valueChanged(TreeSelectionEvent e) {

         DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
         if (node == null) {
         return;
         }
         File node_file = new File(node.getParent() + File.separator + node);
         if (node_file.exists()) {
         editor.panelSouth.setStatus(node.toString());
         editor.tab.addTab(node.getParent() + File.separator + node);
         }

         }
         }
         );*/
    }

    /**
     * Remove all nodes except the root node.
     */
    public void clear() {
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();
        root.removeAllChildren();
        //treeModel.removeNodeFromParent(root);

        //rootNode.removeAllChildren();
        //treeModel.removeNodeFromParent(root);
        //
        treeModel.reload();
        tree.setModel(null);
    }

    public void setPopup(final JPopupMenu popup1) {
        tree.addMouseListener(
                new MouseAdapter() {
                    public void mouseReleased(MouseEvent e) {
                        if (e.isPopupTrigger()) {
                            if (tree.getSelectionPath() != null) {
                                /*File file = new File(getslastSelected() + File.separator + getslastSelectedName());
                                 if (!file.isFile()) {
                                 Component[] components = popup1.getComponents();
                                 for (Component component : components) {
                                 if (component instanceof JMenuItem) {
                                 JMenuItem item = (JMenuItem) component;
                                 if (item.getText().equals("Rename")) {
                                 item.setVisible(false);
                                 }
                                 System.out.println(item.getText());
                                 }
                                 }

                                 } */
                                popup1.show((JComponent) e.getSource(), e.getX(), e.getY());

                            }

                        }
                    }
                }
        );
    }

    public String getslastSelected() {
        String res = "";
        File file = new File(tree.getLastSelectedPathComponent().toString());
        if (file.exists()) {
            //System.out.println(file.getAbsolutePath());
            res = file.getAbsolutePath();
        } else {
            TreePath parent = tree.getLeadSelectionPath();
            //System.out.println(parent.getParentPath());
            //System.out.println(parent.getParentPath().getLastPathComponent().toString());
            res = parent.getParentPath().getLastPathComponent().toString();
        }

        return res;
    }

    public String getslastSelected2() {
        String res = "";
        File file = new File(tree.getLastSelectedPathComponent().toString());
        if (file.exists()) {
            //System.out.println(file.getAbsolutePath());
            res = file.getAbsolutePath();
        } else {
            TreePath parent = tree.getLeadSelectionPath();
            //System.out.println(parent.getParentPath());
            //System.out.println(parent.getParentPath().getLastPathComponent().toString());
            res = parent.getParentPath().getLastPathComponent().toString() + File.separator + file.getName();
        }

        return res;
    }

    public String getslastSelectedName() {
        String res = "";
        File file = new File(tree.getLastSelectedPathComponent().toString());
        if (file.exists()) {
            //System.out.println(file.getAbsolutePath());
            res = file.getName();
        } else {

            res = tree.getLastSelectedPathComponent().toString();
        }

        return res;
    }

    public String getslastSelectedDelete() {
        String res = "";
        File file = new File(tree.getLastSelectedPathComponent().toString());
        if (file.exists()) {
            //System.out.println(file.getAbsolutePath());
            res = file.getAbsolutePath();
        } else {
            TreePath parent = tree.getLeadSelectionPath();
            //System.out.println(parent.getParentPath());
            //System.out.println(parent.getParentPath().getLastPathComponent().toString());
            res = parent.getParentPath().getLastPathComponent().toString() + File.separator + tree.getLastSelectedPathComponent().toString();
        }

        return res;
    }

    public String getslastSelectedParent() {
        String res = "";
        TreePath parent = tree.getLeadSelectionPath();
        res = parent.getParentPath().getLastPathComponent().toString();

        return res;
    }

    /**
     * Remove the currently selected node.
     */
    public void removeCurrentNode() {
        TreePath currentSelection = tree.getSelectionPath();
        if (currentSelection != null) {
            DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) (currentSelection.getLastPathComponent());
            MutableTreeNode parent = (MutableTreeNode) (currentNode.getParent());
            if (parent != null) {
                treeModel.removeNodeFromParent(currentNode);

                return;
            }
        }

        // Either there was no selection, or the root was selected.
        toolkit.beep();
    }

    public void changeCurrentNode(String name) {
        TreePath currentSelection = tree.getSelectionPath();
        if (currentSelection != null) {
            DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) (currentSelection.getLastPathComponent());
            MutableTreeNode parent = (MutableTreeNode) (currentNode.getParent());
            if (parent != null) {
                currentNode.setUserObject(name);
                treeModel.nodeChanged(currentNode);

                return;
            }
        }

        // Either there was no selection, or the root was selected.
        toolkit.beep();
    }

    public void changeCurrentNodeFolder(String name, String old) {
        TreePath currentSelection = tree.getSelectionPath();
        if (currentSelection != null) {
            DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) (currentSelection.getLastPathComponent());
            MutableTreeNode parent = (MutableTreeNode) (currentNode.getParent());
            if (parent != null) {
                currentNode.setUserObject(name);
                treeModel.nodeChanged(currentNode);

                //------------------------------------
                int count = treeModel.getChildCount(currentNode);
                for (int i = 0; i < count; i++) {
                    String name_old = treeModel.getChild(currentNode, i).toString();
                    name_old = name_old.replaceAll(name, old);
                    DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeModel.getChild(currentNode, i);
                    child.setUserObject(name_old);
                    treeModel.nodeChanged(child);
                    System.out.println("child" + treeModel.getChild(currentNode, i));
                }
                return;
            }
        }

        // Either there was no selection, or the root was selected.
        toolkit.beep();
    }

    /**
     * Add child to the currently selected node.
     */
    public DefaultMutableTreeNode addObject(Object child) {
        DefaultMutableTreeNode parentNode = null;
        TreePath parentPath = tree.getSelectionPath();

        if (parentPath == null) {
            parentNode = rootNode;
        } else {
            parentNode = (DefaultMutableTreeNode) (parentPath.getLastPathComponent());
        }

        return addObject(parentNode, child, true);
    }

    public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
            Object child) {
        return addObject(parent, child, false);
    }

    public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
            Object child,
            boolean shouldBeVisible) {
        DefaultMutableTreeNode childNode
                = new DefaultMutableTreeNode(child);

        if (parent == null) {
            parent = rootNode;
        }

        //It is key to invoke this on the TreeModel, and NOT DefaultMutableTreeNode
        treeModel.insertNodeInto(childNode, parent,
                parent.getChildCount());

        //Make sure the user can see the lovely new node.
        if (shouldBeVisible) {
            tree.scrollPathToVisible(new TreePath(childNode.getPath()));
        }
        return childNode;
    }

    /**
     * Add nodes from under "dir" into curTop. Highly recursive.
     */
    public DefaultMutableTreeNode addNodes(DefaultMutableTreeNode curTop, File dir) {
        String curPath = dir.getPath();
        DefaultMutableTreeNode curDir = new DefaultMutableTreeNode(curPath);
        if (curTop != null) { // should only be null at root
            curTop.add(curDir);
        }
        Vector ol = new Vector();
        String[] tmp = dir.list();
        for (int i = 0; i < tmp.length; i++) {
            ol.addElement(tmp[i]);
        }
        Collections.sort(ol, String.CASE_INSENSITIVE_ORDER);
        File f;
        Vector files = new Vector();
        // Make two passes, one for Dirs and one for Files. This is #1.
        for (int i = 0; i < ol.size(); i++) {
            String thisObject = (String) ol.elementAt(i);
            String newPath;
            if (curPath.equals(".")) {
                newPath = thisObject;
            } else {
                newPath = curPath + File.separator + thisObject;
            }
            if ((f = new File(newPath)).isDirectory()) {
                addNodes(curDir, f);
            } else {
                files.addElement(thisObject);
            }
        }
        // Pass two: for files.
        for (int fnum = 0; fnum < files.size(); fnum++) {
            curDir.add(new DefaultMutableTreeNode(files.elementAt(fnum)));
        }
        return curDir;
    }

    class MyTreeModelListener implements TreeModelListener {

        public void treeNodesChanged(TreeModelEvent e) {
            DefaultMutableTreeNode node;
            node = (DefaultMutableTreeNode) (e.getTreePath().getLastPathComponent());

            /*
             * If the event lists children, then the changed
             * node is the child of the node we've already
             * gotten.  Otherwise, the changed node and the
             * specified node are the same.
             */
            int index = e.getChildIndices()[0];
            node = (DefaultMutableTreeNode) (node.getChildAt(index));

            System.out.println("The user has finished editing the node.");
            System.out.println("New value: " + node.getUserObject());
        }

        public void treeNodesInserted(TreeModelEvent e) {
        }

        public void treeNodesRemoved(TreeModelEvent e) {
        }

        public void treeStructureChanged(TreeModelEvent e) {
        }
    }

    private class MyRenderer extends DefaultTreeCellRenderer {

        Icon iconfolder;
        Icon iconfile_agile, iconfile_config, iconfile_tmpl;

        public MyRenderer() {
            iconfolder = createImageIcon("img/folder16.png");
            iconfile_agile = createImageIcon("img/text-x-script.png");
            iconfile_config = createImageIcon("img/text-x-generic.png");
            iconfile_tmpl = createImageIcon("img/x-office-document-template.png");
        }

        public Component getTreeCellRendererComponent(
                JTree tree,
                Object value,
                boolean sel,
                boolean expanded,
                boolean leaf,
                int row,
                boolean hasFocus) {

            super.getTreeCellRendererComponent(
                    tree, value, sel,
                    expanded, leaf, row,
                    hasFocus);

            //System.out.println("" +value.toString());
            File node = new File(value.toString());
            if (node.isDirectory()) {
                setIcon(iconfolder);
                //setIcon(UIManager.getIcon("FileChooser.homeFolderIcon"));
                setText(node.getName());
            } else {
                if (node.getName().endsWith(".agile")) {
                    setIcon(iconfile_agile);
                } else if (node.getName().endsWith(".config")) {
                    setIcon(iconfile_config);
                } else if (node.getName().endsWith(".tpl")) {
                    setIcon(iconfile_tmpl);
                } else {
                    setIcon(iconfile_config);
                }
                setText(node.getName());
            }
            /*if (leaf && isTutorialBook(value)) {
             setIcon(tutorialIcon);
             setToolTipText("This book is in the Tutorial series.");
             } else {
             setToolTipText(null); //no tool tip
             }*/

            return this;
        }

        /*protected boolean isTutorialBook(Object value) {
         DefaultMutableTreeNode node =
         (DefaultMutableTreeNode)value;
         TreeIconDemo2.BookInfo nodeInfo = 
         (TreeIconDemo2.BookInfo)(node.getUserObject());
         String title = nodeInfo.bookName;
         if (title.indexOf("Tutorial") >= 0) {
         return true;
         } 

         return false;
         }*/
        /**
         * Returns an ImageIcon, or null if the path was invalid.
         */
        protected final ImageIcon createImageIcon(String path) {
            java.net.URL imgURL = DynamicTree.class.getResource(path);
            if (imgURL != null) {
                return new ImageIcon(imgURL);
            } else {
                System.err.println("Couldn't find file: " + path);
                return null;
            }
        }
    }

}
